#pragma once

#include <AVUIRotation3D.h>
#include <AVUIVector3D.h>

namespace AVUI {

class AxisAngleRotation3D : public Rotation3D
{
public:
    AxisAngleRotation3D() { };
    AxisAngleRotation3D(const Vector3D& axis, float angle) { set_Angle(angle); set_Axis(axis); };
    virtual ~AxisAngleRotation3D() { }

    virtual Quaternion get_InternalQuaternion();
    DECLARE_ELEMENT(AxisAngleRotation3D, Rotation3D);
                       
    DECLARE_DEPENDENCY_PROPERTY(Angle);
    float get_Angle() { return AVUI::UnboxValue<float>(GetValue(get_AngleProperty())); }
    void set_Angle(float value) { SetValue(get_AngleProperty(), AVUI::BoxValue(value)); } 

    DECLARE_DEPENDENCY_PROPERTY(Axis);
    Vector3D get_Axis() { return AVUI::UnboxValue<Vector3D>(GetValue(get_AxisProperty())); }
    void set_Axis(const Vector3D& value) { SetValue(get_AxisProperty(), AVUI::BoxValue(value)); } 

protected:

    virtual TRefCountedPtr<Freezable> CreateInstanceCore() AVUI_OVERRIDE { return object_allocate<AxisAngleRotation3D>().get_Ptr(); }

private:
    static void AnglePropertyChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* pArgs);
    static void AxisPropertyChanged(DependencyObject* pDO, DependencyPropertyChangedEventArgs* pArgs);
    void AxisPropertyChangedHook(DependencyPropertyChangedEventArgs* e) { m_cachedQuaternionValue = c_dirtyQuaternion; }
    void AnglePropertyChangedHook(DependencyPropertyChangedEventArgs* e) { m_cachedQuaternionValue = c_dirtyQuaternion; }


    static void StaticConstructor();
    static Quaternion c_dirtyQuaternion;
    Quaternion m_cachedQuaternionValue;
};


}; // namespace AVUI
